package com.syf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syf.domain.SysMenu;
import com.syf.domain.SysPrivilege;
import com.syf.domain.SysRolePrivilege;
import com.syf.mapper.SysRolePrivilegeMapper;
import com.syf.model.RolePrivilegesParam;
import com.syf.service.SysMenuService;
import com.syf.service.SysPrivilegeService;
import com.syf.service.SysRolePrivilegeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
*
*
*@author 苏耀奋
*@create 2021-07-11 12:11
*/
@Service
public class SysRolePrivilegeServiceImpl extends ServiceImpl<SysRolePrivilegeMapper, SysRolePrivilege> implements SysRolePrivilegeService {

    @Autowired
    private SysMenuService sysMenuService;//菜单

    @Autowired
    private SysPrivilegeService sysPrivilegeService; //权限

    @Autowired
    private SysRolePrivilegeService sysRolePrivilegeService; //自己的父类接口

    /**
     * 查询角色的权限: 菜单 -> 权限[角色id]
     *
     * @param roleId
     * @return
     */
    @Override
    public List<SysMenu> findSysMenuAndPrivileges(Long roleId) {
        List<SysMenu> list = sysMenuService.list(); // 查询所有的菜单【只有管理员才有这个菜单设置及权限给别人添加权限，无需考虑别的用户】
        if(CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }

        //获取一级菜单(我们在页面显示的是二级菜单,以及二级菜单包含的权限)
        List<SysMenu> rootMenus = list.stream() //流
                .filter(sysMenu -> sysMenu.getParentId() == null) //过滤: 一级菜单的getParentId == null
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(rootMenus)) {
            return Collections.emptyList();
        }

        // 查询所有的二级菜单
        List<SysMenu> subMenus = new ArrayList<>();
        for (SysMenu rootMenu : rootMenus) {
            subMenus.addAll(getChildMenus(rootMenu.getId(), roleId, list)); //addAll: 将指定 collection 中的所有元素添加到列表的尾部
        }
        return subMenus;
    }

    /**
     * 查询菜单的子菜单 (递归)
     *
     * @param parentId 父菜单的ID
     * @param roleId   当前查询的角色的ID
     * @return
     */
    private List<SysMenu> getChildMenus(Long parentId, Long roleId, List<SysMenu> sources) {
        List<SysMenu> childs = new ArrayList<>();  //存储菜单下的子菜单
        for (SysMenu source : sources) {
            if (source.getParentId() == parentId) { //一级菜单下的二级菜单
                childs.add(source); //将二级菜单source存储进 childs
                source.setChilds(getChildMenus(source.getId(), roleId, sources)); // 给该儿子设置儿子(递归: 如果有多级菜单)
                List<SysPrivilege> sysPrivileges = sysPrivilegeService.getAllSysPrivilege(source.getId(), roleId); //查询该(二级)菜单下的所有权限(当前传递的角色使用包含该权限信息 也要进行标记：own=1)
                source.setPrivileges(sysPrivileges); // 该儿子可能包含权限
            }
        }
        return childs;
    }



    /**
     * 新增该角色的权限(角色的ID、角色的包含的 权限id)
     *
     * @param rolePrivilegesParam
     * @return
     */
    @Transactional  //事务
    @Override
    public boolean grantPrivileges(RolePrivilegesParam rolePrivilegesParam) {
        Long roleId = rolePrivilegesParam.getRoleId(); // 角色Id
        //1 先删除之前该角色的权限(注意: 刚创建的新角色没有权限，这时候删除。。。false,不影响)
        sysRolePrivilegeService.remove(new LambdaQueryWrapper<SysRolePrivilege>().eq(SysRolePrivilege::getRoleId, roleId));

        // 移除之前的值成功，封装要批量添加的值(集合)
        List<Long> privilegeIds = rolePrivilegesParam.getPrivilegeIds();
        if (!CollectionUtils.isEmpty(privilegeIds)) { //不为空
            List<SysRolePrivilege> sysRolePrivileges = new ArrayList<>(); //重新封装
            for (Long privilegeId : privilegeIds) {
                SysRolePrivilege sysRolePrivilege = new SysRolePrivilege();
                sysRolePrivilege.setRoleId(rolePrivilegesParam.getRoleId()); //角色id
                sysRolePrivilege.setPrivilegeId(privilegeId); //权限id
                sysRolePrivileges.add(sysRolePrivilege);
            }
            // 2 (批量)新增新的值
            boolean b = sysRolePrivilegeService.saveBatch(sysRolePrivileges);
            return b;
        }
        //如果没有抛异常
        return true ;
    }
}
